package com.tengju.bff.interfaces.shared.render;

import com.tengju.bff.interfaces.shared.AmountType;
import com.tengju.bff.interfaces.shared.AmountVO;
import com.tengju.bff.interfaces.shared.KVVO;
import com.tengju.data.domain.model.analysis.Meta;
import com.tengju.data.domain.model.analysis.MetaType;
import com.tengju.data.domain.model.analysis.Row;
import com.tengju.data.domain.model.analysis.SensitiveLevel;
import com.tengju.data.domain.shared.CastUtil;
import com.tengju.user.domain.shared.SensitiveFieldType;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.CollectionUtils;

import java.util.Collection;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * @author chenhang
 * @Date 2021/8/23
 */
public class MetaUtil {


    public static final Pattern pattern = Pattern.compile("-?[0-9]+.?[0-9]+");

    /**
     * 判断是否是number
     * @param str
     * @return
     */
    public static boolean isNumericzidai(String str) {
        if(StringUtils.isBlank(str)) {
            return false;
        }
        Matcher isNum = pattern.matcher(str);
        if (!isNum.matches()) {
            return false;
        }
        return true;
    }


    public static Object getVal(Meta meta, Row row) {
        if (meta == null || row == null) {
            return null;
        }
        if (StringUtils.isBlank(meta.getFormula())) {
            return row.getValue(meta.getSqlColName());
        }
        String formula = meta.getFormula();
        String[] keys;
        if (formula.contains("/")) {
            keys = formula.split("\\/");
        } else if (formula.contains("*")) {
            keys = formula.split("\\*");
        } else {
            //todo ex
            throw new RuntimeException("meta不支持的操作符");
        }
        String key1 = keys[0].trim();
        String key2 = keys[1].trim();
        double val1 = isNumericzidai(key1) ? CastUtil.castDouble(key1) : CastUtil.castDouble(row.getValue(key1));
        double val2 = isNumericzidai(key2) ? CastUtil.castDouble(key2) : CastUtil.castDouble(row.getValue(key2));
        if (val2 == 0) {
            return 0;
        }
        return val1 / val2;
    }

    public static AmountVO getAmount(Meta meta, Row row, Collection<Meta> metaList) {
        AmountType amountType = AmountType.parseByMeta(meta.getMetaType());
        AmountVO amount = new AmountVO(amountType,MetaUtil.getVal(meta,row));
        maskAmount(amount,meta);
        bindMetas(meta,amount,row,metaList);
        return amount;
    }

    private static void maskAmount(AmountVO amount, Meta meta) {
        if (meta == null || meta.getSensitiveLevel().equals(SensitiveLevel.low) || meta.getMetaType() == null) {
            return;
        }
        MetaType metaType = meta.getMetaType();
        if (metaType.equals(MetaType.Name)) {
            amount.mask(SensitiveFieldType.NAME);
        }
    }

    private static void bindMetas(Meta masterMeta, AmountVO amount, Row row, Collection<Meta> metaList) {
        if (CollectionUtils.isEmpty(masterMeta.getBindMetas())) {
            return;
        }
        Map<String, Meta> metaMap = metaList.stream()
                .collect(Collectors.toMap(Meta::getColName, v -> v, (v1, v2) -> v1));
        for (String bindMetaKey : masterMeta.getBindMetas()) {
            Meta bindMeta = metaMap.get(bindMetaKey);
            AmountVO bindAmount = MetaUtil.getAmount(bindMeta,row, metaList);
            amount.addExtra(KVVO.of(bindMeta.getShowName(),bindAmount.toString()));
        }
    }
}
